/**
 * HTML安全工具函数集合
 * 提供全面的HTML转义和安全处理功能
 */

// 基础HTML字符转义（保持现有功能）
export function escapeForHtml(str: string): string {
  if (!str) return ''
  return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#39;')
}

/**
 * 彻底解决script标签问题：使用Base64编码
 * 这是最安全的方法，完全避免HTML解析器的干扰
 */
export function encodeForJavaScript(str: string): string {
  if (!str) return 'null'

  try {
    // 使用Base64编码，彻底避免HTML解析问题
    const encoded = btoa(unescape(encodeURIComponent(str)))
    return `"${encoded}"`
  } catch (error) {
    console.error('Base64编码失败，使用备用方案:', error)
    // 备用方案：字符级转义
    return JSON.stringify(str.replace(/<\/script>/gi, '<\\/script>'))
  }
}

/**
 * 解码Base64编码的字符串（用于JavaScript中）
 */
export function createDecodeFunction(): string {
  return `
    function decodeBase64String(encoded) {
      try {
        if (!encoded || encoded === 'null') return '';
        // 移除引号
        const base64 = encoded.replace(/^"|"$/g, '');
        // Base64解码
        return decodeURIComponent(escape(atob(base64)));
      } catch (error) {
        console.error('Base64解码失败:', error);
        return encoded;
      }
    }
  `
}

/**
 * 安全地将对象转换为JSON字符串
 * 使用Base64编码处理字符串值
 */
export function safeJSONStringify(obj: any): string {
  try {
    // 预处理对象，对字符串值进行Base64编码
    const processedObj = processObjectForSafety(obj)
    return JSON.stringify(processedObj)
  } catch (error) {
    console.error('JSON序列化失败:', error)
    return 'null'
  }
}

/**
 * 递归处理对象，对字符串进行安全编码
 */
function processObjectForSafety(obj: any): any {
  if (obj === null || obj === undefined) {
    return obj
  }

  if (typeof obj === 'string') {
    // 检查是否包含危险内容
    if (containsDangerousContent(obj)) {
      return {
        _type: 'encoded_string',
        _value: btoa(unescape(encodeURIComponent(obj)))
      }
    }
    return obj
  }

  if (Array.isArray(obj)) {
    return obj.map(item => processObjectForSafety(item))
  }

  if (typeof obj === 'object') {
    const processed: any = {}
    for (const key in obj) {
      if (obj.hasOwnProperty(key)) {
        processed[key] = processObjectForSafety(obj[key])
      }
    }
    return processed
  }

  return obj
}

/**
 * 检查字符串是否包含危险内容
 */
function containsDangerousContent(str: string): boolean {
  const dangerousPatterns = [/<\/script>/gi, /<script/gi, /<\/style>/gi, /<\/iframe>/gi, /javascript:/gi, /vbscript:/gi]

  return dangerousPatterns.some(pattern => pattern.test(str))
}

/**
 * 创建对象解码函数（用于JavaScript中）
 */
export function createObjectDecodeFunction(): string {
  return `
    function decodeObjectStrings(obj) {
      if (!obj || typeof obj !== 'object') return obj;
      
      if (Array.isArray(obj)) {
        return obj.map(item => decodeObjectStrings(item));
      }
      
      // 处理编码的字符串
      if (obj._type === 'encoded_string' && obj._value) {
        try {
          return decodeURIComponent(escape(atob(obj._value)));
        } catch (error) {
          console.error('解码字符串失败:', error);
          return '';
        }
      }
      
      // 递归处理对象属性
      const decoded = {};
      for (const key in obj) {
        if (obj.hasOwnProperty(key)) {
          decoded[key] = decodeObjectStrings(obj[key]);
        }
      }
      return decoded;
    }
  `
}

import { sanitizeCodeSnippet, SANITIZE_PRESETS, SanitizeOptions } from './codeSanitizer'

/**
 * 智能验证和清理代码片段
 * 自动剔除危险内容，保留安全部分
 */
export function validateCodeSnippet(
  codeSnippet: string,
  sanitizeMode: 'strict' | 'moderate' | 'permissive' = 'moderate'
): {
  isValid: boolean
  sanitized: string
  warnings: string[]
  cleaningLog?: {
    isModified: boolean
    removedElements: string[]
    warnings: string[]
    info: string[]
  }
} {
  const warnings: string[] = []
  let sanitized = codeSnippet || ''

  // 检查长度限制
  const MAX_CODE_LENGTH = 50000
  if (sanitized.length > MAX_CODE_LENGTH) {
    sanitized = sanitized.substring(0, MAX_CODE_LENGTH)
    warnings.push(`代码片段过长，已截断至${MAX_CODE_LENGTH}字符`)
  }

  // 选择清理策略
  const sanitizeOptions = SANITIZE_PRESETS[sanitizeMode.toUpperCase() as keyof typeof SANITIZE_PRESETS]

  // 执行智能清理
  const sanitizeResult = sanitizeCodeSnippet(sanitized, sanitizeOptions)

  // 合并警告信息
  warnings.push(...sanitizeResult.warnings)

  // 如果内容被修改，记录信息
  if (sanitizeResult.isModified) {
    console.info('代码清理完成:', {
      removedElements: sanitizeResult.removedElements.length,
      warnings: sanitizeResult.warnings.length,
      info: sanitizeResult.info.length
    })
  }

  // 最终安全检查
  const remainingThreats = detectRemainingThreats(sanitizeResult.sanitized)
  if (remainingThreats.length > 0) {
    warnings.push(...remainingThreats)
  }

  return {
    isValid: remainingThreats.length === 0,
    sanitized: sanitizeResult.sanitized,
    warnings,
    cleaningLog: {
      isModified: sanitizeResult.isModified,
      removedElements: sanitizeResult.removedElements,
      warnings: sanitizeResult.warnings,
      info: sanitizeResult.info
    }
  }
}

/**
 * 检测清理后是否还有剩余威胁
 */
function detectRemainingThreats(code: string): string[] {
  const threats: string[] = []

  // 这些应该在清理后不再存在
  const criticalPatterns = [
    { pattern: /javascript:\s*[^"'\s]/gi, message: '仍包含JavaScript协议' },
    { pattern: /on\w+\s*=\s*[^"'\s]/gi, message: '仍包含内联事件处理器' },
    { pattern: /eval\s*\(/gi, message: '仍包含eval函数' }
  ]

  criticalPatterns.forEach(({ pattern, message }) => {
    if (pattern.test(code)) {
      threats.push(message)
    }
  })

  return threats
}

/**
 * 检测代码片段的类型
 */
function detectCodeType(code: string): string | null {
  const typeChecks = [
    { pattern: /<\?php/i, type: 'PHP' },
    { pattern: /<script[^>]*type\s*=\s*["']module["']/i, type: 'ES6 Module' },
    { pattern: /<script[^>]*>/i, type: 'JavaScript/HTML' },
    { pattern: /<style[^>]*>/i, type: 'CSS/HTML' },
    { pattern: /<!DOCTYPE\s+html/i, type: 'HTML Document' },
    { pattern: /import\s+.*from\s+['"`]/i, type: 'ES6 Import' },
    { pattern: /export\s+(default\s+)?/i, type: 'ES6 Export' },
    { pattern: /function\s+\w+\s*\(/i, type: 'JavaScript Function' },
    { pattern: /class\s+\w+/i, type: 'JavaScript Class' },
    { pattern: /interface\s+\w+/i, type: 'TypeScript Interface' },
    { pattern: /def\s+\w+\s*\(/i, type: 'Python Function' },
    { pattern: /public\s+class\s+\w+/i, type: 'Java Class' },
    { pattern: /#include\s*<.*>/i, type: 'C/C++ Header' }
  ]

  for (const check of typeChecks) {
    if (check.pattern.test(code)) {
      return check.type
    }
  }

  return null
}

/**
 * 为不同类型的代码提供特定的验证
 */
export function validateCodeByType(
  code: string,
  expectedType?: string
): {
  isValid: boolean
  detectedType: string | null
  suggestions: string[]
} {
  const detectedType = detectCodeType(code)
  const suggestions: string[] = []

  if (expectedType && detectedType && detectedType !== expectedType) {
    suggestions.push(`检测到的代码类型(${detectedType})与预期类型(${expectedType})不符`)
  }

  // 根据代码类型提供特定建议
  if (detectedType === 'JavaScript/HTML' && code.includes('<script')) {
    suggestions.push('HTML中的script标签是正常的，已安全处理')
  }

  if (detectedType === 'ES6 Module' && code.includes('type="module"')) {
    suggestions.push('ES6模块脚本标签是现代JavaScript的标准用法')
  }

  return {
    isValid: true, // 大多数代码类型都是有效的
    detectedType,
    suggestions
  }
}

/**
 * 生成安全的HTML属性
 */
export function generateRequiredAttr(required?: boolean): string {
  return required ? 'required' : ''
}

export function generatePlaceholderAttr(placeholder?: string): string {
  return placeholder ? `placeholder="${escapeForHtml(placeholder)}"` : ''
}

export function createUniqueId(baseId: string): string {
  // 生成唯一ID,格式为: baseId_timestamp_随机字符串
  // 使用 crypto.getRandomValues 生成更安全的随机数
  return `${baseId}_${Date.now()}_${Array.from(crypto.getRandomValues(new Uint8Array(8)))
    .map(b => b.toString(16).padStart(2, '0'))
    .join('')}`
}
